#include "mtlib.c"
#include "pd_pcoms.c"
#include "pd_pcom.c"
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>

unsigned char * estado;
unsigned int * conexiones = NULL;
unsigned int cantConexiones = 0;
unsigned char centroMensajes = 0;
unsigned long cantidadSectores = 0;
int conexionActiva = -1;

#include "pd_ecom.c"

#define imprimirCaracter(ARCH, CAR) ((((CAR) < 32) || ((CAR) > 126)) ? putc('.', (ARCH)) : putc((CAR), (ARCH)))

pthread_t crearThread(void);
void * main2 (void *);
void mostrarDatosSector(FILE *, void *);

int main (void) {
  centroMensajes = mtf_obtener_descriptor(1024);
  estado = malloc(1);
  *estado = 1;
  pthread_t nuevoThread = crearThread();
  comando_t comando;
  while (*estado) {
    comando = obtenerComando();
    *estado = ejecutarComando(comando);
  }
  unsigned int posConexion;
  for (posConexion = 0; posConexion < cantConexiones; posConexion ++)
    mtf_desconectar(centroMensajes, conexiones[posConexion]);
  free(conexiones);
  mtf_liberar_descriptor(centroMensajes);
  pthread_join(nuevoThread, NULL);
  free(estado);
  return 0;
}

pthread_t crearThread (void) {
  pthread_t num;
  pthread_create(&num, NULL, &main2, NULL);
  return num;
}

void * main2 (void * param) {
  mti_mensaje mensaje;
  void * datos = malloc(512);
  long numSector;
  char motivo;
  FILE * arch = fopen("output.txt", "w");
  while (*estado) {
    if (!mtf_recibir_mensajes(centroMensajes)) continue;
    mensaje = mtf_siguiente_mensaje(centroMensajes);
    if (mensaje.categoria == MTA_HANDSHAKE) {
      fprintf(arch, "Recibido handshake.\n");
      mtf_descartar_mensaje(centroMensajes, mensaje.codigo);
      continue;
    }
    if ((mensaje.categoria == MTA_ACEPTAR) || (mensaje.categoria == MTA_CERRAR)) {
      mtf_descartar_mensaje(centroMensajes, mensaje.codigo);
      continue;
    }
    if (mensaje.tipo == MTR_DATOS_SECTOR) {
      mtf_obtener_datos(centroMensajes, mensaje.codigo, (long *) &numSector, (void **) &datos);
      fprintf(arch, "Contenido del sector %ld:\n", numSector);
      mostrarDatosSector(arch, datos);
    } else if (mensaje.tipo == MTR_NO_LEYO_SECTOR) {
      mtf_obtener_datos(centroMensajes, mensaje.codigo, (long *) &numSector, (char *) &motivo);
      fprintf(arch, "Sector %ld: no leyo (motivo %hhu).\n", numSector, motivo);
    } else if (mensaje.tipo == MTR_NULL)
      fprintf(arch, "Conexion activa.\n");
    else if (mensaje.tipo == MTR_ESCRIBIO_SECTOR) {
      mtf_obtener_datos(centroMensajes, mensaje.codigo, (long *) &numSector);
      fprintf(arch, "Sector %ld: se escribio satisfactoriamente.\n", numSector);
    } else if (mensaje.tipo == MTR_NO_ESCRIBIO_SECTOR) {
      mtf_obtener_datos(centroMensajes, mensaje.codigo, (long *) &numSector, (char *) &motivo);
      fprintf(arch, "Sector %ld: no escribio (motivo %hhu).\n", numSector, motivo);
    } else if (mensaje.tipo == MTE_NULL)
      mtf_enviar_mensaje(centroMensajes, mensaje.remitente, MTR_NULL);
    else
      fprintf(arch, "Recibido mensaje desconocido %hu.\n", mensaje.tipo);
    mtf_descartar_mensaje(centroMensajes, mensaje.codigo);
  }
  fclose(arch);
  free(datos);
  return param;
}

void mostrarDatosSector (FILE * archivo, void * datos) {
  char * d = datos;
  unsigned int p1, p2;
  for (p1 = 0; p1 < 32; p1 ++) {
    fprintf(archivo, "%03X: ", p1 * 16);
    for (p2 = 0; p2 < 16; p2 ++)
      fprintf(archivo, "%02hhX ", d[p1 * 16 + p2]);
    for (p2 = 0; p2 < 16; p2 ++)
      imprimirCaracter(archivo, d[p1 * 16 + p2]);
    putc('\n', archivo);
  }
}